<script>
import { ScheduleManager } from "./ScheduleManager.js";
import CollapseWrapper from "./CollapseWrapper.vue";
import $ from "jquery";
const getOffsetTop = (pel, el) => {
  let pOffset = $(pel).offset();
  let elOffset = $(el).offset();
  return elOffset.top - pOffset.top;
};
export default {
  props: {
    data: Array,
  },
  provide() {
    return {
      getManager: () => {
        return this.scheduleManager;
      },
      toggleFold: this.toggleFold,
      foldIdsInfo: this.foldIdsInfo,
      getIsShow: this.getIsShow,
    };
  },
  data() {
    return {
      categoryGroups: [],
      dockerGroups: null,
      operation: null,
      operatingShowType: "link", // fix, link
      patientActiveds: [],
      scrollOffset: {},
      isTransitionRunning: false,
      foldIdsInfo: [],
    };
  },
  watch: {
    data: {
      handler(vals) {
        let categoryGroups = vals.filter((item) => item.type !== "operating");
        let operation = vals.find((item) => item.type === "operating");
        let firstItems = { ...categoryGroups[0] };
        let firstSortKey = firstItems.config.sortKey;
        if (firstSortKey) {
          firstItems.list = firstItems.list.sort(
            (a, b) => a[firstSortKey] - b[firstSortKey]
          );
        }

        this.categoryGroups = categoryGroups.slice(1).reduce(
          (a, b) => {
            let prevItems = a[a.length - 1];
            let { list, config } = b;
            let groupMap = {};
            list.forEach((item) => {
              // let id = item[config.idKey || 'id'];
              let pid = item[config.pIdKey || "pid"];
              if (groupMap[pid]) {
                groupMap[pid].push(item);
              } else {
                groupMap[pid] = [item];
              }
            });
            let newList = [];
            prevItems.list.forEach((item) => {
              let id = item[prevItems.config.idKey || "id"];
              let children = groupMap[id];
              if (children) {
                if (config.sortKey) {
                  children.sort((a1, a2) => {
                    return a1[config.sortKey] - a2[config.sortKey];
                  });
                }
                newList.push(...children);
              }
            });
            return [...a, { ...b, list: newList }];
          },
          [firstItems]
        );

        let operationPatient =
          this.categoryGroups[this.categoryGroups.length - 1];
        let { list: pList, config: pConfig } = operationPatient || {};
        if (operation) {
          let { list: oList, config: oConfig } = operation;
          let oMap = {};
          oList.forEach((item) => {
            let pid = item[oConfig.pIdKey || "pid"];
            if (oMap[pid]) {
              oMap[pid].push(item);
            } else {
              oMap[pid] = [item];
            }
          });
          let newOList = [];
          pList.forEach((item) => {
            let id = item[pConfig.idKey || "id"];
            let children = oMap[id];
            if (children) {
              if (oConfig.sortKey) {
                children.sort((a1, a2) => {
                  return a1[oConfig.sortKey] - a2[oConfig.sortKey];
                });
              }
            }
            newOList.push({
              id: `${id}_group`,
              pid: id,
              list: children || [],
              config: oConfig,
            });
          });
          this.operation = {
            ...operation,
            list: newOList,
          };
        }
      },
      immediate: true,
    },
    foldIdsInfo() {
      this.$nextTick(() => {
        this.scheduleManager.updateEdges();
      });
    },
  },
  computed: {
    groups() {
      if (this.dockerGroups) {
        return [...this.categoryGroups, this.dockerGroups];
      }
      return this.categoryGroups;
    },
  },
  created() {
    this.scheduleManager = new ScheduleManager(this);
  },
  mounted() {
    this.scheduleManager.init(this.$refs.wrapper, this.$refs.svg);
    this.scheduleManager.drawEdge();
  },
  methods: {
    initData() {},
    setPatientShowType(type) {
      this.patientActiveds = [];
      this.operatingShowType = type;
      this.$nextTick(() => {
        setTimeout(() => {
          this.scheduleManager.drawEdge();
          setTimeout(() => {
            this.scheduleManager.updateEdges();
          }, 30);
        }, 310);
      });
    },
    collapseTrans(type) {
      if (type === "beforeEnter" || type === "beforeLeave") {
        clearInterval(this.timer);
        this.isTransitionRunning = true;
        this.timer = setInterval(() => {
          this.scheduleManager.drawEdge();
        }, 25);
      } else if (type === "afterLeave" || type === "afterEnter") {
        clearInterval(this.timer);
        this.isTransitionRunning = false;
        this.scheduleManager.drawEdge();
      }
    },
    toggleFold(type, id) {
      let index = this.foldIdsInfo.findIndex((item) => item.id === id);
      if (index >= 0) {
        this.foldIdsInfo.splice(index, 1);
      } else {
        this.foldIdsInfo.push({
          id,
          type,
        });
      }
    },

    findParentFold(curId, index, ignore) {
      let currentFold = !!this.foldIdsInfo.find((item) => item.id === curId);
      if (!ignore && currentFold) {
        return true;
      }
      if (index > -1) {
        let { config, list } = this.categoryGroups[index] || { config: {} };
        if (config && list && list.length > 0) {
          let { idKey = "id", pIdKey = "pid" } = config;
          let curData = list.find((item) => item[idKey] === curId);
          if (curData) {
            let pid = curData[pIdKey];
            if (this.findParentFold(pid, index - 1)) {
              return true;
            }
          }
        }
      }
      return false;
    },
    getIsShow(type, id) {
      if (type === "operating") {
        return this.getOperatingShow(id);
      }
      let index = this.categoryGroups.findIndex((item) => item.type === type);
      return !!this.findParentFold(id, index, true);
    },
    getOperatingShow(groupId) {
      let curGroup = this.operation.list.find((item) => item.id === groupId);
      let pid = curGroup.pid;
      return this.findParentFold(pid, this.categoryGroups.length - 1, false);
    },
    activedChange(id, type) {
      let pid, pType;
      let scrollWrap;
      if (type === "operating") {
        for (let i = 0; i < this.operation.list.length; i++) {
          let group = this.operation.list[i];
          let currentNodeIndex = group.list.findIndex(
            (item) => item[group.config.idKey || "id"] === id
          );
          if (currentNodeIndex > -1) {
            pid = group.list[currentNodeIndex][group.config.pIdKey || "pid"];
            break;
          }
        }
        pType = this.categoryGroups[this.categoryGroups.length - 1].type;
        scrollWrap = this.$refs.operatingWrapper;
      } else {
        let currentCateIndex = this.categoryGroups.findIndex(
          (item) => item.type === type
        );
        let currentCate = this.categoryGroups[currentCateIndex];
        if (currentCate) {
          let currentNodeIndex = currentCate.list.findIndex(
            (item) => item[currentCate.config.idKey || "id"] === id
          );
          if (currentNodeIndex > -1) {
            pid =
              currentCate.list[currentNodeIndex][
                currentCate.config.pIdKey || "pid"
              ];
            pType = this.categoryGroups[currentCateIndex - 1]?.type;
          }
          scrollWrap = this.$refs.collapseWrapper.find(
            (item) => item.type === type
          );
        }
      }
      if (pid && pType && scrollWrap) {
        let node = this.scheduleManager.getNodeById(id);
        let scrollNode = scrollWrap.$refs.listWrap;
        let offsetTop = getOffsetTop(scrollNode, node.$el);
        console.log(offsetTop);
        this.setActivedAndScroll(pid, pType, offsetTop);
      }
    },
    setActivedAndScroll(id, type, viewOffsetTop) {
      let wraperInst = this.$refs.collapseWrapper.find(
        (item) => item.type === type
      );
      if (wraperInst) {
        wraperInst.activedId = id;
        wraperInst.activeNames = [];
        let node = this.scheduleManager.getNodeById(id);
        if (node && node.$el) {
          let elScrollTop = getOffsetTop(
            node.$el.parentElement.firstElementChild,
            node.$el
          );
          $(wraperInst.$refs.listWrap).animate(
            {
              scrollTop: elScrollTop - viewOffsetTop,
            },
            "slow"
          );
          // node.$el.scrollIntoView({
          //   behavior: "smooth",
          //   block: "nearest",
          //   // inline: "nearest",
          // });
        }
      }
      let pid, pType;
      let currentCateIndex = this.categoryGroups.findIndex(
        (item) => item.type === type
      );
      let currentCate = this.categoryGroups[currentCateIndex];
      if (currentCate) {
        let currentNodeIndex = currentCate.list.findIndex(
          (item) => item[currentCate.config.idKey || "id"] === id
        );
        if (currentNodeIndex > -1) {
          pid =
            currentCate.list[currentNodeIndex][
              currentCate.config.pIdKey || "pid"
            ];
          pType = this.categoryGroups[currentCateIndex - 1]?.type;
        }
      }
      if (pid && pType) {
        this.setActivedAndScroll(pid, pType, viewOffsetTop);
      }
    },
  },

  components: {
    CollapseWrapper,
  },
};
</script>
<template>
  <div class="surgical-schedule" ref="wrapper">
    <svg
      ref="svg"
      class="surgical-schedule-svg"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
    ></svg>
    <div class="schedule-wrap">
      <el-card
        class="schedule-card"
        :key="item.name"
        v-for="item in groups"
        shadow="hover"
      >
        <div slot="header" class="card-header">
          <div class="--left">
            <span>{{ item.name }}</span>
          </div>
          <div class="--right">
            <i class="iconfont icon-androidgengduo-copy"></i>
          </div>
        </div>
        <collapse-wrapper
          :type="item.type"
          :config="item.config"
          :list="item.list"
          ref="collapseWrapper"
          @activedChange="activedChange"
          @toggleFold="toggleFold"
        ></collapse-wrapper>
      </el-card>
      <el-card class="schedule-card" shadow="hover" v-if="operation">
        <div slot="header" class="card-header">
          <div class="--left">
            <span>{{ operation.name }}</span>
          </div>
          <div class="--right">
            <!-- <i -->
            <!--   class="iconfont icon-layout-right" -->
            <!--   :class="{ highlight: operatingShowType === 'group' }" -->
            <!--   aria-hidden="true" -->
            <!--   @click="setPatientShowType('group')" -->
            <!-- ></i> -->
            <i
              class="iconfont icon-chain"
              :class="{ highlight: operatingShowType === 'link' }"
              aria-hidden="true"
              @click="setPatientShowType('link')"
            ></i>
            <i
              class="iconfont icon-Frame"
              :class="{ highlight: operatingShowType === 'fix' }"
              @click="setPatientShowType('fix')"
            ></i>
          </div>
        </div>
        <collapse-wrapper
          ref="operatingWrapper"
          :type="operation.type"
          :config="operation.config"
          :list="operation.list"
          :operatingShowType="operatingShowType"
          @activedChange="activedChange"
        ></collapse-wrapper>
      </el-card>
    </div>
  </div>
</template>
<style>
.surgical-schedule {
  ::-webkit-scrollbar {
    display: block;
    width: 4px;
    height: 4px;
    background: transparent;
  }
  ::-webkit-scrollbar-corner {
    background-color: transparent;
  }
  ::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.2);
    border: none;
    border-radius: 4px;
  }
  ::-webkit-scrollbar-track {
    background: transparent;
  }
}
.butterflies-link {
  fill: none;
  stroke-width: 1.5px;
  pointer-events: none;
}
.surgical-schedule-svg {
  position: absolute;
  pointer-events: auto !important;
  overflow: visible !important;
  path.--base {
    stroke: #d8d8d8;
    &.highlight1 {
      /*stroke: #eb9328; #f8d38f;orange*/
      stroke: #1677ff;
      z-index: 499;
    }
    &.highlight2 {
      stroke: #1677ff;
      z-index: 500;
    }
  }
}
</style>
<style scoped lang="less">
.surgical-schedule {
  position: relative;
  height: 100%;
  background-color: #fff;

  .schedule-wrap {
    display: flex;
    height: 100%;
    .schedule-card {
      display: flex;
      flex-direction: column;
      width: 260px;
      min-width: 260px;
      margin-right: 60px;
      // border: 1px solid #d9d9d9;
      background: radial-gradient(
          29.8% 8.61% at 4.313725490196078% 96.65071770334929%,
          rgba(235, 244, 255, 0.5) 0%,
          rgba(255, 255, 255, 0) 100%
        ),
        radial-gradient(
          194.51% 56.46% at 16.470588235294116% 61.602870813397125%,
          rgba(236, 241, 255, 0.5) 0%,
          rgba(255, 255, 255, 0) 100%
        ),
        radial-gradient(
          40.78% 13.04% at 92.94117647058823% 88.51674641148325%,
          rgba(237, 242, 252, 1) 0%,
          rgba(255, 255, 255, 0.5) 100%
        ),
        linear-gradient(
          180deg,
          rgba(255, 255, 255, 0.5) 0%,
          rgba(255, 255, 255, 0) 100%
        ),
        rgba(247, 248, 250, 1);
      background-blend-mode: normal normal normal normal normal;
      border: 1px solid rgba(0, 0, 0, 0.15);
      box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.02);
      &:last-child {
        flex: 1;
        margin-right: 0;
      }
      ::v-deep {
        > .el-card__header {
          padding: 10px;
          // border: none;
          // margin-bottom: 8px;
        }
        > .el-card__body {
          overflow: hidden;
          flex: 1;
          padding: 0;
        }
      }
      .card-header {
        display: flex;
        align-items: center;
        .--left {
          flex: 1;
        }
        .--right {
          color: rgba(0, 0, 0, 0.45);
          display: flex;
          align-items: center;
          > .iconfont {
            display: block;
            width: 16px;
            height: 16px;
            font-size: 14px;
            margin-right: 10px;
            cursor: pointer;
            &.highlight {
              color: #1677ff;
            }
            &:last-child {
              margin-right: 0;
            }
          }
        }
      }
    }
  }
  .cell-move {
    transition: transform 13s;
  }
}
</style>
